package com.smsc.headend.connector.service.protocol;

import cn.hutool.core.lang.Tuple;
import com.smsc.headend.connector.bo.*;
import com.smsc.headend.connector.exception.UDISDeviceConException;
import com.smsc.headend.module.asset.dmo.ComConfigDMO;
import com.smsc.headend.module.asset.dmo.DLMSConfigDMO;
import com.smsc.headend.module.asset.entity.ComEntity;
import com.smsc.headend.module.asset.entity.Meter;
import com.smsc.headend.module.protocol.ProtocolType;
import com.smsc.headend.module.task.dto.ConnectorTask;
import gurux.dlms.secure.GXDLMSSecureClient;
import io.netty.channel.Channel;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public interface DLMSPacketCodecService extends PacketCodecService {

    byte[] convertConnectorTask(ConnectorTask connectorTask, Channel channel);

    /**
     * decode register packet
     * use DLMS decode first
     *
     * @param result
     * @return
     */
    Tuple getLogicalAddrFromLoggingFrame(byte[] result);

    /**
     * 判断是否是心跳包
     *
     * @param result
     * @return
     */
    boolean isHeartBeat(byte[] result);

    /**
     * 回复心跳包
     *
     * @param channel
     * @param terminal
     */
    void heartBeatResp(Channel channel, ComEntity terminal);

    byte[] getResponseBytes(byte[] result);

    /**
     * ;
     * 处理业务报文，传回上层模块
     *
     * @param terminal
     * @param netAddress
     * @param result
     * @param context
     * @return
     */
    DevicePacketHandleResult handleDeviceServicePacket(Channel channel, ComEntity terminal, String netAddress, byte[] result, TaskContext context);

    /**
     * 如果terminal是dcu，meterNo为空时，直接与dcu建立连接。如果meterNO不为空，包头添加信息
     *
     * @param packetBytes
     * @param terminal
     * @param deviceAddress
     * @return
     */
    byte[] wrapPrefixToPacket(byte[] packetBytes, ComEntity terminal, String deviceAddress);

    /**
     * DLMS-gateway dcu返回的报文中提取meterNo
     *
     * @param packet
     * @return
     */
    UnwrappedPacket unwrapPrefixPacket(byte[] packet);

    /**
     * build AARQ with device or device under terminal
     *
     * @param terminal
     * @param netAddress
     * @param connectorTask
     * @param aaState
     * @return
     * @throws UDISDeviceConException
     */
    TaskContext buildTaskContext(ComEntity terminal, String netAddress, ConnectorTask connectorTask, AssociationState aaState) throws UnsupportedEncodingException;

    /**
     * re-initialize  taskContext for new Task
     *
     * @param context
     * @param connectorTask
     * @param aaState
     * @return
     */
    TaskContext initializeTaskContext(TaskContext context, ConnectorTask connectorTask, AssociationState aaState);

    /**
     * 获取对应设备的DLMS Config
     *
     * @param terminal
     * @param meter
     * @return
     */
    DLMSConfigDMO getDLMSConfigDMO(ComEntity terminal, Meter meter);


    /**
     * 判断packet的类型
     *
     * @param result
     * @param terminal
     * @param comConfigDMO
     * @return
     */
    PacketType getPacketType(byte[] result, ComEntity terminal, ComConfigDMO comConfigDMO) throws NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException;

    /**
     * hls电表报文加密
     *
     * @param pdu
     * @param client
     * @return
     */
    byte[] encryptHLSPacket(byte[] pdu, GXDLMSSecureClient client) throws NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException;

    /**
     * 解密HLS packet
     *
     * @param gloPdu
     * @param client
     * @return
     */
    byte[] decryptHLSPacket(byte[] gloPdu, GXDLMSSecureClient client) throws NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException;

    boolean needEncrypt(GXDLMSSecureClient client);

    Integer invokeIdAdd(String connectionInfo, byte[] packetByte, String netAddress, TaskContext context, String taskNo) throws NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException;

    boolean isAssociationRelease(byte[] result, String netAddress, String responseType, ProtocolType protocolType);

    boolean isDLMSGatewayTransparentFailedPkg(byte[] result);

    boolean isChannelSpecialPkg(byte[] result);

    byte[] getNotificationResponse(String data);

    String setCosemMessage(byte[] result);

    /**
     * 处理非COSEM报文
     *
     * @param result
     * @param channel
     */
    void handleUntranslatablePacket(byte[] result, Channel channel);

    boolean resendConnectorTask(ComEntity comEntity, Channel netAddress);

    /**
     * 处理COSEM 推送报文报文类型:DataNotification/EventRequestNotification
     *
     * @param responseType
     * @param channel
     * @param cosemApdu
     * @return
     */
    Boolean acceptHandleNotifications(String responseType, Channel channel, byte[] cosemApdu);

    String getPduXml();

    String getCosemXml();

    byte[] initialTaskAndSend(ComEntity terminal, AssociationState aaState, Channel channel, boolean isRebuildAa);

    void buildAAFailedCallBack(ComEntity terminal, Channel channel);

    void configRetryBO(boolean noRetry, Channel channel, byte[] businessPacket, ConnectorTask connectorTask, String deviceAddress);
}
